package com.jichangxiu.common.utils;

import cn.hutool.core.util.ObjectUtil;
import com.jichangxiu.common.entity.bo.Record;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

public class ObjUtils extends ObjectUtil {

    public static void trimBeanStr(Object bean) {
        if (bean.getClass().getCanonicalName().equals("com.jichangxiu.common.core.entity.bo.Record"))
            return;
        if (ObjectUtil.isNotEmpty(bean)) {
            // 获取所有的字段包括 public,private,protected,private
            Field[] fields = bean.getClass().getDeclaredFields();
            for (Field f : fields) {
                // 对其中的集合同样进行空格处理
                if (f.getType().getName().equals("java.util.List")) {
                    List<Object> objects = objCastList(getFieldValue(bean, f.getName()), Object.class);
                    for (Object object : objects)
                        trimBeanStr(object);
                }
                if (f.getType().getName().equals("java.lang.String")) {
                    String key = f.getName();
                    if (bean.getClass().getName().equals("com.jichangxiu.common.core.entity.bo.Record") && key.equals(Record.RECORD_KEY))
                        continue;
                    // 获取字段名
                    Object value = getFieldValue(bean, key);
                    if (value == null)
                        continue;
                    setFieldValue(bean, key, value.toString().trim());
                }
            }
        }
    }

    public static <R> List<R> objCastList(Object obj, Class<R> clazz) {
        List<R> list = new ArrayList<>();
        if (obj instanceof List<?>)
            for (Object o : (List<?>) obj)
                list.add(clazz.cast(o));
        return list;
    }

    public static Object getFieldValue(Object bean, String fieldName) {
        try {
            String methodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
            Object rObject = null;
            Method method = null;
            @SuppressWarnings("rawtypes")
            Class[] classArr = new Class[0];
            method = bean.getClass().getMethod(methodName, classArr);
            rObject = method.invoke(bean);
            return rObject;
        } catch (InvocationTargetException | NoSuchMethodException | IllegalAccessException ex) {
            throw new RuntimeException("【ObjUtils】反射获取对象属性值异常", ex);
        }
    }

    public static void setFieldValue(Object bean, String fieldName, Object value) {
        try {
            String methodName = "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
            // 利用反射调用 bean.set 方法将 value 设置到字段
            @SuppressWarnings("rawtypes")
            Class[] classArr = new Class[1];
            classArr[0] = "java.lang.String".getClass();
            Method method = bean.getClass().getMethod(methodName, classArr);
            method.invoke(bean, value);
        } catch (InvocationTargetException | NoSuchMethodException | IllegalAccessException ex) {
            throw new RuntimeException("【ObjUtils】反射设置对象属性值异常", ex);
        }
    }

    public static void formatObject(Object object) {
        if (object instanceof List)
            formatList((List<?>) object);
        else
            formatDateObject(object);
    }

    private static void formatList(List<?> list) {
        for (Object item : list)
            formatDateObject(item);
    }

    private static void formatDateObject(Object object) {
        if (object != null) {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            // 获取对象的所有属性，并检查是否为 Date 类型
            // 假设这里使用反射获取对象的属性和对应的值，并对Date类型属性进行格式化处理
            // 获取对象的所有属性，包括私有属性
            Field[] fields = object.getClass().getDeclaredFields();
            for (Field field : fields) {
                if (field.getType() == Date.class) {
                    try {
                        // 设置私有属性可访问
                        field.setAccessible(true);
                        Date date = (Date) field.get(object);
                        if (date != null) {
                            String formattedDate = dateFormat.format(date);
                            // 将格式化后的值设置回对象的对应属性
                            field.set(object, formattedDate);
                        }
                    } catch (Exception ex) {
                        throw new RuntimeException("【ObjUtils】重新设置【" + field.getType().getName() + "】字段值异常", ex);
                    }
                } else if (field.getType() == Object.class) {
                    // 如果属性是一个对象类型，进行递归处理
                    try {
                        field.setAccessible(true);
                        Object nestedObject = field.get(object);
                        if (nestedObject != null)
                            formatObject(nestedObject);
                    } catch (Exception ex) {
                        throw new RuntimeException("【ObjUtils】重新设置【" + field.getType().getName() + "】字段值异常", ex);
                    }
                }
            }
        }
    }

    public static <T> T getValueByClass(Object obj, Class<T> cs) {
        String obj2 = String.valueOf(obj);
        Object obj3;
        if (cs.equals(String.class))
            obj3 = obj2;
        else if (cs.equals(int.class) || cs.equals(Integer.class))
            obj3 = Integer.valueOf(obj2);
        else if (cs.equals(long.class) || cs.equals(Long.class))
            obj3 = Long.valueOf(obj2);
        else if (cs.equals(short.class) || cs.equals(Short.class))
            obj3 = Short.valueOf(obj2);
        else if (cs.equals(byte.class) || cs.equals(Byte.class))
            obj3 = Byte.valueOf(obj2);
        else if (cs.equals(float.class) || cs.equals(Float.class))
            obj3 = Float.valueOf(obj2);
        else if (cs.equals(double.class) || cs.equals(Double.class))
            obj3 = Double.valueOf(obj2);
        else if (cs.equals(boolean.class) || cs.equals(Boolean.class))
            obj3 = Boolean.valueOf(obj2);
        else
            obj3 = (T) obj;
        return (T) obj3;
    }

    public static <T> List<Field> reflectForField(Class<T> clazz) {
        Class tmpClazz = clazz;
        List<Field> fieldList = new ArrayList<>();
        while (tmpClazz != null) {
            if (tmpClazz.equals(Object.class)) {
                tmpClazz = tmpClazz.getSuperclass();
                continue;
            }
            fieldList.addAll(new ArrayList<>(Arrays.asList(tmpClazz.getDeclaredFields())));
            tmpClazz = tmpClazz.getSuperclass();
        }
        Field[] fields = new Field[fieldList.size()];
        fieldList.toArray(fields);
        return fieldList;
    }

}
